package utilities;

import java.io.FileInputStream;
import java.util.Properties;

/**
 * Time properties static class.
 * @author pcdejager
 *
 */
public class TimeProperties {
    /**
     * Hide the default constructor.
     * @throws Exception if cannot load properties
     */
    protected TimeProperties() throws Exception {
        Properties properties = new Properties();
        FileInputStream inputStream = new FileInputStream(
                "src\\main\\resources\\time.properties");
        properties.load(inputStream);
        inputStream.close();

        referenceYear = Integer.parseInt(properties.getProperty("RefYear"));
        daysInAYear = Integer.parseInt(properties.getProperty("DaysInAYear"));

        int months = Integer.parseInt(properties.getProperty("MonthsInAYear"));
        daysInMonth = new int[months];
        monthNames = new String[months];
        for (int count = 1; count <= months; ++count) {
            String name = "Month" + String.valueOf(count);
            monthNames[count - 1] = properties.getProperty(name + "Name");
            daysInMonth[count - 1] = Integer.parseInt(
                    properties.getProperty(name + "Days"));
        }
    }

    /**
     * Get the number of days in a year.
     * @return The number of days
     */
    public final int daysInAYear() {
        return daysInAYear;
    }

    /**
     * Get the number of months in a year.
     * @return The number of months
     */
    public final int monthsInAYear() {
        return daysInMonth.length;
    }

    /**
     * Get the number of days in a specific month.
     * @param month The month index
     * @return The number of days in month. -1 if index incorrect
     */
    public final int daysInMonth(final int month) {
        if ((month < 1) || (month > daysInMonth.length)) {
            return -1;
        }
        return daysInMonth[month - 1];
    }

    /**
     * Get the name of a specific month.
     * @param month The month index
     * @return The name of the month. null if index incorrect.
     */
    public final String monthName(final int month) {
        if ((month < 1) || (month > daysInMonth.length)) {
            return null;
        }
        return monthNames[month - 1];
    }


    /**
     * Get the year.
     * @param day The days since reference date
     * @return The year
     */
    public final int getYear(final int day) {
        if (day < 1) {
            return referenceYear;
        }
        return ((day - 1) / daysInAYear) + referenceYear;
    }

    /**
     * Get the month.
     * @param day The days since reference date
     * @return The month
     */
    public final int getMonth(final int day) {
        if (day < 1) {
            return 0;
        }
        int temp = (day - 1) % daysInAYear;
        int pos = 0;
        while (daysInMonth[pos] <= temp) {
            temp -= daysInMonth[pos];
            ++pos;
        }
        return (pos + 1);
    }

    /**
     * Get the day.
     * @param day The days since reference date
     * @return The day
     */
    public final int getDay(final int day) {
        if (day < 1) {
            return 0;
        }
        int temp = (day - 1) % daysInAYear;
        int pos = 0;
        while (daysInMonth[pos] <= temp) {
            temp -= daysInMonth[pos];
            ++pos;
        }
        return (temp + 1);
    }

    /**
     * Get the instance of the singleton class.
     * @return The instance
     */
    public static TimeProperties getInstance() {
        if (instance == null) {
            try {
                instance = new TimeProperties();
            } catch (Exception e) {
                instance = null;
            }
        }
        return instance;
    }

    /**
     * Static instance of the class.
     */
    private static TimeProperties instance = null;

    /**
     * The number of days in a year.
     */
    private int daysInAYear = 0;
    /**
     * The days in each month.
     */
    private int[] daysInMonth = null;
    /**
     * The names of each month.
     */
    private String[] monthNames = null;
    /**
     * The reference year.
     */
    private int referenceYear = 0;
}
